<?php

class Application_Model_DomainObject {

	protected $_dbTable;

	protected $_tableName;

	/**
	 * 构造方法，初始化对象，并默认设置持久化操作类
	 * 如果$options类型是array,则用array中的值初始化对象
	 * 如果$options类型为数字,则试该参数为ID，并用此ID重建该对象
	 * @param array $options
	 */
	public function __construct($options = null)
	{
		$ref = get_class($this);
		$this->_tableName = str_replace('Application_Model_', 'Application_Model_DbTable_', $ref);

		if (is_array($options)) {
			$this->setOptions($options);
		}else if (is_numeric($options)){
			$this->getDbTable()->setById($this,$options);
		}
	}

	/**
	 * 用魔术方法模拟出类似 $object->Property 的操作方法。
	 * 如果定义了setProperty,优先使用set方法设值,如果没有，则直接给_property变量的设值
	 * @param unknown_type $name
	 * @param unknown_type $value
	 * @throws Exception
	 */
	public function __set($name, $value)
	{
		$method = 'set' . $name;
		if (('mapper' == $name) || !method_exists($this, $method)) {
			$prop = '_'.$this->lcfirstex($name);
			if(property_exists($this, $prop)){
				$this->$prop = $value;
				return;
			}
			else
                throw new Exception('设置了不存在的属性，请检查:'.$name);
		}
		$this->$method($value);
	}

	/**
	 * 用魔术方法模拟出类似 $object->Property 的操作方法。
	 * 如果定义了getProperty,优先使用get方法返回,如果没有，则直接返回_property变量的值
	 * @param unknown_type $name
	 * @throws Exception
	 */
	public function __get($name)
	{
		$method = 'get' . $name;
		if (('mapper' == $name) || !method_exists($this,$method)) {
			$prop = '_'.$this->lcfirstex($name);
			if(property_exists($this, $prop))
                return $this->$prop;
			else
                throw new Exception('获取了不存在的属性，请检查:'.$name);
		}
		return $this->$method();
	}

	/**
	 * 用指定的值初始化对象
	 * @param array $options
	 * @return Application_Model_DomainObject
	 */
	public function setOptions(array $options)
	{
		$mapper= $this->getDbTable()->getMapper();
		foreach ($options as $key => $value) {
			if(in_array($key, $mapper) ||in_array($this->lcfirstex($key), $mapper)){
				$method = ucfirst($key);
				$this->$method=$value;
			}
		}
		return $this;
	}

	/**
	 * 设置对象的持久化操作类
	 * @param string|Application_Model_DbTable_DomainObject $dbTable
	 * @throws Exception
	 */
	public function setDbTable($dbTable){
		if(is_string($dbTable)){
			$dbTable=new $dbTable();
		}

		if(!$dbTable instanceof Zend_Db_Table_Abstract){
			throw new Exception('Invalid table data gateway provided');
		}

		$this->_dbTable=$dbTable;
		return $this;
	}

	/**
	 * 返回一个操作
	 * @return Application_Model_DbTable_DomainObject
	 */
	public function getDbTable(){
		if(null === $this->_dbTable){
			$this->setDbTable($this->_tableName);
		}
		return $this->_dbTable;
	}

	/**
	 * 保存对对象的修改，如果有ID，则Updadte，如果没有ID，则新增一个对象
	 * @return Application_Model_DomainObject
	 */
	public function save(){
		return $this->getDbTable()->save($this);
	}
    
    /**
     * 新增对像 
     */
    public function insertId(){
        $this->getDbTable()->insertId($this);
    }

    /**
	 *  按ID查找对象
	 * @param Application_Model_DomainObject $id 对象ID
	 */
	public function find($id){

		return $this->getDbTable()->getById($id);
	}

	/**
	 * 返回第一个满足条件的对象
	 * @param array $where
	 * @return Application_Model_DomainObject
	 */
	public function queryOne(array $where){
		return $this->getDbTable()->queryOne($where);
	}

	/**
	 * 返回所有满足条件的对象
	 * @param array $where 条件数组
     * @param string $orderBy 排序
	 * @return array
	 */
	public function queryAll(array $where,$orderBy){
		return $this->getDbTable()->queryAll($where,$orderBy);
	}
    

    /**
	 * 删除当前对象
	 */
	public function delete(){
		$this->getDbTable()->del(array('id'=>$this->Id));
	}

	/**
	 * 根据ID重建持久化对象
	 * @param type $id
	 * @return Application_Model_DomainObject
	 */
	public static function load($id){
		$class=  get_called_class();
		$tableName = str_replace('Application_Model_', 'Application_Model_DbTable_', $class);
		$db = new $tableName;
		return $db->getById($id);
	}

	/**
	 * 返回数据库对象
	 * @return Application_Model_DbTable_DomainObject
	 */
	protected static function getDao(){
		$class=  get_called_class();
		$tableName = str_replace('Application_Model_', 'Application_Model_DbTable_', $class);
		$db = new $tableName;
		return $db;
	}

	public function lcfirstex($string)
	{
		if(function_exists('lcfirst'))
		{
			return lcfirst($string);
		}
		else
		{
			if (!$string) return null;
			return preg_replace('/(^[A-Z])/', strtolower(substr($string, 0, 1)), $string);
		}
	}
}